package com.kelp.codetoolkit.utils.frame

import com.intellij.database.util.common.isNotNullOrEmpty
import com.intellij.openapi.module.Module
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiJavaFile
import com.intellij.psi.PsiManager


/**
 * @author: liuyuebai
 * @date: 2024/8/7 07:01
 * @description:
 */
object SpringUtil {

    private val cache = mutableMapOf<String, PsiFile>()
    private val cacheVirtualFile = mutableMapOf<String, VirtualFile>()

    fun getPackageName(psiFile: PsiFile,parentDirectory:String?): String {
        if (psiFile is PsiJavaFile) {
            var packageName = psiFile.packageName
            if (parentDirectory.isNotNullOrEmpty){
                packageName += ".$parentDirectory"
            }
            return packageName
        }
        return "";
    }

    fun getSpringBootApplicationPath(module: Module): String {
        val moduleApplicationFile = getModuleApplicationFile(module)
        if (moduleApplicationFile != null) {
            return moduleApplicationFile.virtualFile.parent.path
        }
        return ""
    }


    fun getModuleApplicationFile(module: Module): PsiFile? {
        val applicationVirtualFile = cache[module.name]
        if (applicationVirtualFile != null) return applicationVirtualFile
        val rootManager = ModuleRootManager.getInstance(module)
        val sourceRoots = rootManager.sourceRoots
        val virtualFiles:MutableList<VirtualFile> = mutableListOf()
        val psiFiles:MutableList<PsiFile> = mutableListOf()
        val classList:MutableList<PsiClass> = mutableListOf()

        sourceRoots.forEach { source ->
            getJavaFile(source,virtualFiles);
        }
        virtualFiles.forEach { javaFile ->
            PsiManager.getInstance(module.project).findFile(javaFile)?.let { psiFile ->
                psiFiles.add(psiFile)
            }
        }
        psiFiles.forEach{psiFile ->
            if(psiFile is PsiJavaFile){
                classList.addAll(psiFile.classes)
            }
        }
        classList.forEach { psiClass->
            if(psiClass.hasAnnotation("org.springframework.boot.autoconfigure.SpringBootApplication")){
                cache[module.name] = psiClass.containingFile
                return psiClass.containingFile
            }
        }
        return null
    }

    fun getResourcesPath(module: Module): String? {
        return getResourceFile(module)?.path
    }

    private fun getJavaFile(directory: VirtualFile,javaFiles: MutableList<VirtualFile>){
        val children = directory.children
        if(children == null || children.isEmpty()){
            return
        }
        for (virtualFile in children) {
            if (virtualFile.isDirectory){
                getJavaFile(virtualFile,javaFiles)
            }else{
                if (virtualFile.extension == "java"){
                    javaFiles.add(virtualFile)
                }

            }
        }
    }


   private fun getResourceFile(module: Module): VirtualFile? {
        val key = module.name + ":" + "resources"
        val resourcesFile = cacheVirtualFile[key]
        if (null != resourcesFile) {
            return resourcesFile
        }
        val rootManager = ModuleRootManager.getInstance(module)
        val sourceRoots = rootManager.sourceRoots
        sourceRoots.forEach { root ->
            if (root.path.contains("src/main/resources")){
                return root
            }
        }
        return null
    }
}